# coding: utf-8

# VKontakte.Ru module by RankoR & pythonall.ru

__author__ = 'RankoR'

import urllib
import urllib2
import httplib
import re


# TODO:
# * Do we need the ID var? maybe only fullID?
# * Maybe make connection keep-alive?
# * Is "chas" var in send_message const?


# BUGS:
# * Probably a bug in name parsing while getting friends list (min name length is 5)

class Vkontakte:
    def __init__(self, email, password):
        self.id             = None
        self.fullID         = None
        self.cookie         = None
        self.p              = None
        self.constHeaders   = None
        self.friends        = []
        self.friendsPhones  = []
        self.email          = email
        self.password       = password
        self.loggedIn       = False

    # Login function
    def login(self):
        # Returns unique ID on login.vk.com
        host = 'http://login.vk.com/?act=login'
        post = urllib.urlencode({'email' : self.email,
                                 'expire' : '',
                                 'pass' : self.password,
                                 'vk' : ''})

        headers = {'User-Agent' : 'Mozilla/5.0 (Windows; U; Windows NT 5.1; ru; rv:1.9.0.13) Gecko/2009073022 Firefox/3.0.13 (.NET CLR 3.5.30729)',
                   'Host' : 'login.vk.com',
                   'Referer' : 'http://vkontakte.ru/index.php',
                   'Connection' : 'close',
                   'Pragma' : 'no-cache',
                   'Cache-Control' : 'no-cache',
                  }

        try:
            conn         = urllib2.Request(host, post, headers)
            data         = urllib2.urlopen(conn)
            cookie_src   = data.info().get('Set-Cookie')
        except:
            print "Exception while logging in. Probably, wrong password."
            return False

        html = data.read()
        
        try:
            self.id         = re.search('l=([^;]+);', cookie_src).group(1)  # "l" value in cookies id our ID
            self.p          = re.search('p=([^;]+);', cookie_src).group(1)  # id dunno what's "p"
            index           = html.index("value='")
            if index == -1:
                return False
            index += 7
            length          = html.index("'", index)
            if length == -1:
                return False
            self.remixsid   = html[index:length]
        except:
            print "id or p not found!"
            return False

        self.fullID = "id" + self.id

        # Go to the redirect page
        host = "http://vkontakte.ru/login.php?act=slogin&al_frame=1&hash=" + self.remixsid + "&s=1"
        conn = urllib2.Request(host)
        data = urllib2.urlopen(conn)

        self.loggedIn   = True
        return True


    # Do request and return contents
    def do_request(self, host, page, method = "GET", post = None):

        if not self.loggedIn:
            return None


        constHeaders = {'User-Agent' : 'Mozilla/5.0 (Windows; U; Windows NT 5.1; ru; rv:1.9.0.13) Gecko/2009073022 Firefox/3.0.13 (.NET CLR 3.5.30729)',
                        'Host' : host,
                        'Connection' : 'close',
                        'Pragma' : 'no-cache',
                        'Cache-Control' : 'no-cache',
                        'Cookie' : "remixchk=5; remixmid=; remixsid=" + self.remixsid + "; remixgid=; remixemail=; remixpass="
                        }

        try:

            if post != None:
                post_data = urllib.urlencode(post)
                conn      = urllib2.Request("http://" + host + page, post_data, constHeaders)
                data      = urllib2.urlopen(conn)
                return data.read()
            else:
                conn = httplib.HTTPConnection(host)
                conn.request(method, page, headers = constHeaders)
                
            res = conn.getresponse()
        except:
            print "do_request(", host, page, ") generated an exception"
            return None

        return res.read()



    # Opens user's page and returns it's contents
    def get_page(self):

        return self.do_request("/" + self.fullID)

    
    # Returns friends count
    # Parses IDs, Names and Mobile Phones
    def get_friends(self):

        html       = self.do_request("m.vkontakte.ru", "/friends")

        if (html == None) or (len(html) == 0):
            return 0

        # Find all the pages

        friends_pages = re.findall("/friends[0-9]{1,3}", html)

        if len(friends_pages) == 0:
            return 0

        for page in friends_pages:

            print "Processing", page
            html_tmp = self.do_request("m.vkontakte.ru", page)
            html    += html_tmp

        # Find IDs
        friends_ids = re.findall("id[0-9]{1,12}", html, re.DOTALL)

        if friends_ids == None:
            return 0

        # Find Names
        friends_names = re.findall("\">.{1,64}</a></b><br/>", html)

        if friends_names == None:
            return 0

        names_len = len(friends_names)

        # Let's join ID's and names
        for i in range(len(friends_ids)):

            if i < names_len:
                pair = { friends_ids[i][2:15] : friends_names[i] } # Check it !! ([2:15])
            else:
                pair = { friends_ids[i][2:15] : "" }


            self.friends.append(pair)


        # Parse phones
        self.friendsPhones = re.findall("tel:\+{0,1}[0-9]{5,15}", html)

        phones = []
        for phone in self.friendsPhones:
            phones.append(phone[4:15])

        self.friendsPhones = phones

        return len(self.friends)


    # Sending message to id
    def send_message(self, id, title, text):
        html = self.do_request("m.vkontakte.ru", "/?act=write&to=" + id)

        try:
            chas = re.findall("chas\" value=\"[a-z0-9]{1,32}", html)[0][13:32]
        except:
            print "Failed to parse chas var (send_message)"
            return False

        post = { "to_id"    : id,
                 "to_reply" : 0,
                 "chas"     : chas,
                 "title"    : title,
                 "message" : text
                }

        html = self.do_request("m.vkontakte.ru", "/mailsent?pda=1", "POST", post)

        return html != None